#ifndef _BTREE_H
#define _BTREE_H

#include <sys/types.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>

#include "util/trace.h"

/*
    TOP  - terminal operand
    cop  - comparison operator
    BEXP - boolean expression
    bop  - boolean operator

    Grammar:

    BEXP -> bop(1) BEXP BEXP
    BEXP -> cop(1) TOP(3) TOP(3)

    bop -> &&
    bop -> ||

    cop -> >
    cop -> <
    cop -> >=
    cop -> <=
    cop -> ==

    TOP -> 0 <int16>      // constant uint32_t
    TOP -> 1 <int16>      // input uint32_t
 */

#define TABS(n) for(int ttt = 0 ; ttt < n; printf("\t"), ttt++);

const int BEXP_LIMIT    =   7; // in bytes, minimum needed to interpret a BEXP node
const int TOP_LIMIT     =   3; // in bytes, minimum needed to interpret a TOP node

const int BOP_AND   = 0;
const int BOP_OR    = 1;

const int bop_num = BOP_OR+1;

const int    ibop[] = {BOP_AND, BOP_OR};

const int COP_G     = 2;
const int COP_L     = 3;
const int COP_GE    = 4;
const int COP_LE    = 5;
const int COP_EQ    = 6;

const int cop_max = COP_EQ;
const int op_num  = cop_max+1;

const int    icop[] = {COP_G, COP_L, COP_GE, COP_LE, COP_EQ};

const char* const ops[] = {"&&", "||", ">", "<", ">=", "<=", "=="};

const int AM_CONST  =   0;
const int AM_INPUT  =   1;

const int am_num = AM_INPUT+1;

const char* const ams[] = {"const", "input"};

uint32_t TOP(char** exp, char* end, uint32_t* in, int inmax, int level, bool print = false);

uint32_t COP(char** exp, char* end, uint32_t* in, int inmax, int level, bool print = false);

uint32_t TOP(char** exp, char* end, uint32_t* in, int inmax, int level, bool print);

uint32_t BEXP(char** exp, char* end, uint32_t* in, int inmax, int level, bool print);

void btree_prg_print(char** exp, char* end);

void btree_randomise(char** exp, int length);

void btree_init(int constmax);

bool btree_eval(char** exp, char* end, float* in);

bool btree_eval(char** exp, int len, float* in);

float btree_print(char** exp, char* end, float* in);

float btree_print(char** exp, int len, float* in);

void btree_save(const char* path, char* exp, int length);

// returns length
int btree_load(const char* path, char** exp);

void btree_mutate(char** exp, int length);

#endif
